﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace Cityship
{
    class Entity
    {
        private Ship ship;
        private Deck deck;

        public string Name;

        private Vector2 _location;
        public Vector2 Location
        {
            get { return _location; }
            set
            {
                _location = value;
                if (_location.X < 0) _location.X = 0;
                if (_location.Y < 0) _location.Y = 0;
                if (_location.X > deck.GetWidth - 1) _location.X = deck.GetWidth - 1;
                if (_location.Y > deck.GetHeight - 1) _location.Y = deck.GetHeight - 1;
            }
        }

        private Vector2 inertia;

        public float Rotation;
        public Vector2 Scale;
        public string spriteName;
        private float speed;

        private bool invalidControlState;
        public bool Dead;
        private int decayTime;

        public Entity(Ship ship, string name, Point entryPoint, Deck startingDeck)
        {
            this.ship = ship;
            deck = startingDeck;
            deck.Entities.Add(this);
            Name = name;
            Location = new Vector2(entryPoint.X + 0.5f + deck.GetWidth / 2, entryPoint.Y + 0.5f + deck.GetHeight / 2);
            Rotation = (float)(MathHelper.Pi * Utility.rand.NextDouble() * 2);
            Scale = new Vector2(1, 1);
            spriteName = "default";
            //speed = Utility.rand.Next(200, 500) * 0.0001f;
            speed = 0.01f;
            invalidControlState = false;
            decayTime = 2400;
        }

        public void Die() //Bad design, no cake!
        {
            deck.Entities.Remove(this);
            ship.RemoveEntity(this);
        }

        public bool CheckDecayed(GameTime gameTime)
        {
            Scale *= 0.99f;
            decayTime -= gameTime.ElapsedGameTime.Milliseconds;
            if (decayTime < 0)
                return true;
            return false;
        }

        public void TryMoveForward(float speedModifier)
        {
            Vector2 CDirection = new Vector2((speed * speedModifier) * (float)Math.Cos(Rotation), (speed * speedModifier) * (float)Math.Sin(Rotation));
            ApplyMovement(CDirection);
        }

        private void ApplyMovement(Vector2 direction)
        {
            Location += direction;
            inertia = direction;
        }

        public void Turn(float angle)
        {
            Rotation += angle;
        }

        public void Wander()
        {
            if (Utility.rand.Next(0, 10) == 0)
            {
                Rotation += Utility.rand.Next(-10, 11) * 0.01f;
            }
            TryMoveForward(1.0f);
        }

        public void Control(KeyboardState k_state)
        {
            
            if (k_state.IsKeyDown(Keys.Up))
            {
                TryMoveForward(2.0f);
            }
            if (k_state.IsKeyDown(Keys.Down))
            {
                TryMoveForward(-1.0f);
            }
            if (k_state.IsKeyDown(Keys.Left))
            {
                Turn(-0.035f);
            }
            if (k_state.IsKeyDown(Keys.Right))
            {
                Turn(0.035f);
            }
        }

        public void Update(KeyboardState k_state)
        {

            if (!Dead)
            {
                if (!invalidControlState)
                {
                    Control(k_state);
                    Wander();
                }
                CheckMovement();
            }
            else
            {
                if (invalidControlState)
                {
                    Drift();
                }
            }
        }

        private void Drift()
        {
            Location += inertia;
            invalidControlState = true;
            Rotation += (Utility.rand.Next(0, 2) == 0 ? 0.08f : -0.08f);

            Location += currentTile().AirFlow;
        }

        private Tile currentTile()
        {
            return deck.TileGrid[(int)Location.X, (int)Location.Y];
        }

        private void CheckMovement()
        {
            invalidControlState = false;


            Location += currentTile().AirFlow;

            if (currentTile().Type == TileType.Wall)
            {

                ApplyMovement(deck.ToNearestValidFloorTile(Location, 1) * 0.1f);
                invalidControlState = true;
                Rotation += (Utility.rand.Next(0, 2) == 0 ? MathHelper.PiOver4 : -MathHelper.PiOver4);
            }
            else if (currentTile().Type == TileType.Nothing)
            {
                Drift();
                invalidControlState = true;
                Dead = true;
                ship.AddToDyingEntities(this);
            }
        }

    }
}
